package cn.iocoder.yudao.framework.common.util.http;

import cn.hutool.core.util.StrUtil;
import cn.iocoder.yudao.framework.common.util.json.JsonUtils;
import okhttp3.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.util.Map;
import java.util.concurrent.TimeUnit;

/**
 * 默认客户端5秒连接超时，10秒读取超时
 * http请求异常的情况返回结果为null,需自行处理该状况
 * Created by LifeFly on 2017-01-13.
 */
public class HttpOKUtils {

    private static final Logger LOG = LoggerFactory.getLogger(HttpOKUtils.class);
    public static OkHttpClient DEFAULT_CLIENT = new OkHttpClient.Builder().connectTimeout(5, TimeUnit.SECONDS).readTimeout(10, TimeUnit.SECONDS).build();

    public static String DEFAULT_ENCODE = "utf-8";

    public static final MediaType MEDIA_TYPE_JSON = MediaType.parse("application/json; charset=utf-8");

    public static final MediaType MEDIA_TYPE_FORM = MediaType.parse("application/x-www-form-urlencoded; charset=utf-8");

    public static String getStringByGet(String path) {
        return getStringByGet(path, null, null, DEFAULT_CLIENT, DEFAULT_ENCODE);
    }

    public static String getStringByGet(String path, Map<String, String> params) {
        return getStringByGet(path, params, null, DEFAULT_CLIENT, DEFAULT_ENCODE);
    }

    public static String getStringByGet(String path, Map<String, String> params, Map<String, String> header) {
        return getStringByGet(path, params, header, DEFAULT_CLIENT, DEFAULT_ENCODE);
    }

    public static String getStringByGet(String path, Map<String, String> params, Map<String, String> header, OkHttpClient client, String encode) {
        long beginTime = System.currentTimeMillis();
        String result = "";
        if (StrUtil.isBlank(path)) {
            return null;
        }
        if (client == null) {
            client = DEFAULT_CLIENT;
        }
        if (StrUtil.isBlank(encode)) {
            encode = DEFAULT_ENCODE;
        }
        try {
            if (params != null && !params.isEmpty()) {
                StringBuilder url = new StringBuilder(path);
                url.append("?");
                for (Map.Entry<String, String> entry : params.entrySet()) {
                    url.append(entry.getKey()).append("=");
                    url.append(URLEncoder.encode(entry.getValue(), encode));
                    url.append("&");
                }
                url.deleteCharAt(url.length() - 1);
                path = url.toString();
            }
            Request.Builder requestBuilder = new Request.Builder();
            if (header != null) {
                requestBuilder.headers(Headers.of(header));
            }
            requestBuilder.url(path).build();
            try (Response resp = client.newCall(requestBuilder.build()).execute()) {
                result = resp.body() != null ? resp.body().string() : null;
                if (resp.isSuccessful()) {
                    return result;
                } else {
                    result = StrUtil.format("响应码异常:{}，响应内容为:{}", resp.code(), result);
                }
            }
        } catch (Exception e) {
            LOG.warn(StrUtil.format("调用 {} 发生异常，异常信息为:{}", path, e.getMessage()), e);
            result = StrUtil.format("调用接口发生异常：{}", e.getMessage());
        } finally {
            long endTime = System.currentTimeMillis();
            LOG.info("调用: {} ;耗时:{}ms;入参:{};出参:{};header:{}", path, (endTime - beginTime), JsonUtils.toJsonString(params), result, JsonUtils.toJsonString(header));
        }
        return null;
    }

    public static String getStringByPost(String path, Map<String, String> params) {
        return getStringByPost(path, params, null, DEFAULT_CLIENT, DEFAULT_ENCODE);
    }

    public static String getStringByPost(String path, Map<String, String> params, Map<String, String> header) {
        return getStringByPost(path, params, header, DEFAULT_CLIENT, DEFAULT_ENCODE);
    }

    public static String getStringByPost(String path, Map<String, String> params, Map<String, String> header, OkHttpClient client, String encode) {
        long beginTime = System.currentTimeMillis();
        String result = "";
        if (client == null) {
            client = DEFAULT_CLIENT;
        }
        if (StrUtil.isBlank(encode)) {
            encode = DEFAULT_ENCODE;
        }
        try {
            StringBuilder data = new StringBuilder();
            if (params != null && !params.isEmpty()) {
                for (Map.Entry<String, String> entry : params.entrySet()) {
                    data.append(entry.getKey()).append("=");
                    data.append(URLEncoder.encode(entry.getValue(), encode));
                    data.append("&");
                }
                data.deleteCharAt(data.length() - 1);
            }
            Request.Builder requestBuilder = new Request.Builder();
            if (header != null) {
                requestBuilder.headers(Headers.of(header));
            }
            requestBuilder.url(path).post(RequestBody.Companion.create(data.toString(), MEDIA_TYPE_FORM));
            try (Response resp = client.newCall(requestBuilder.build()).execute()) {
                result = resp.body() != null ? resp.body().string() : null;
                if (resp.isSuccessful()) {
                    return result;
                } else {
                    result = StrUtil.format("响应码异常:{}，响应内容为:{}", resp.code(), result);
                }
            }
        } catch (Exception e) {
            LOG.warn(StrUtil.format("调用 {} 发生异常，异常信息为:{}", path, e.getMessage()), e);
            result = StrUtil.format("调用接口发生异常：{}", e.getMessage());
        } finally {
            long endTime = System.currentTimeMillis();
            LOG.info("调用: {} ;耗时:{}ms;入参:{};出参:{};header:{}", path, (endTime - beginTime), JsonUtils.toJsonString(params), result, JsonUtils.toJsonString(header));
        }
        return null;
    }

    public static String getStringByPost(String path, String jsonParam) {
        return getStringByPost(path, jsonParam, null, DEFAULT_CLIENT, DEFAULT_ENCODE);
    }

    public static String getStringByPost(String path, String jsonParam, Map<String, String> header) {
        return getStringByPost(path, jsonParam, header, DEFAULT_CLIENT, DEFAULT_ENCODE);
    }

    public static String getStringByPost(String path, String jsonParam, Map<String, String> header, OkHttpClient client, String encode) {
        long beginTime = System.currentTimeMillis();
        String result = "";
        if (client == null) {
            client = DEFAULT_CLIENT;
        }
        if (StrUtil.isBlank(encode)) {
            encode = DEFAULT_ENCODE;
        }
        try {
            if (StrUtil.isNotBlank(jsonParam) && !"utf-8".equalsIgnoreCase(encode)) {
                jsonParam = new String(jsonParam.getBytes(StandardCharsets.UTF_8), encode);
            }
            Request.Builder requestBuilder = new Request.Builder();
            if (header != null) {
                requestBuilder.headers(Headers.of(header));
            }
            requestBuilder.url(path).post(RequestBody.Companion.create(jsonParam, MEDIA_TYPE_JSON));
            try (Response resp = client.newCall(requestBuilder.build()).execute()) {
                result = resp.body() != null ? resp.body().string() : null;
                if (resp.isSuccessful()) {
                    return result;
                } else {
                    result = StrUtil.format("响应码异常:{}，响应内容为:{}", resp.code(), result);
                }
            }
        } catch (Exception e) {
            LOG.warn(StrUtil.format("调用 {} 发生异常，异常信息为:{}", path, e.getMessage()), e);
            result = StrUtil.format("调用接口发生异常：{}", e.getMessage());
        } finally {
            long endTime = System.currentTimeMillis();
            LOG.info("调用: {} ;耗时:{}ms;入参:{};出参:{};header:{}", path, (endTime - beginTime), jsonParam, result, JsonUtils.toJsonString(header));
        }
        return null;
    }
}
